﻿using InDepth2Demo.Chapter6;
using System;
using System.Collections.Generic;
using System.Linq;

namespace InDepth2Demo.Chapter10
{
    /// <summary>
    /// 10.3 .NET 3.5 中的扩展方法
    /// </summary>
    internal class ExtensionMethod_NET35
    {
        // 用Enumerable.Range打印数字0~9 
        public static void Call()
        {
            var collection = Enumerable.Range(0, 10);
            foreach (var item in collection)
            {
                Console.WriteLine(item);
            }
        }

        //延迟执行的例子
        public static void Call2()
        {
            var numbers = new List<int> { 1, 2, 3, 4, 5 };
            numbers.Reverse();

            // 在这里，查询还没有执行
            Console.WriteLine("查询尚未执行");

            // 实际访问查询结果时，查询才会执行
            foreach (var number in numbers)
            {
                Console.WriteLine(number);
            }
        }
        // numbers.Reverse() 创建了一个查询，但并没有立即执行。
        // 只有在 foreach 循环中迭代 numbers 时，查询才真正执行，并且会一次性加载所有数据到内存中进行反转操作。


        // 用 Lambda 表达式作为 Where 方法的参数，从而只保留奇数
        public static void Call3()
        {
            var collection = Enumerable.Range(0, 10)
                                        .Where(x => x % 2 != 0)
                                        .Reverse();
            foreach (var element in collection)
            {
                Console.WriteLine(element);
            }
        }

        // 将 IteratorExample 类中 Call2 方法改进，即两个方法链接起来。
        public static void Call4()
        {
            foreach (string line in IteratorExample.ReadLines($"D:\\1.txt")
                                                    .Where(line => line.StartsWith("using")))
            {
                Console.WriteLine(line);
            }
        }

        // 用Lambda表达式和匿名类型进行 投影
        public static void Call5()
        {
            var collection = Enumerable.Range(0, 10)
                                        .Where(x => x % 2 != 0)
                                        .Reverse()
                                        .Select(x => new { Original = x, SquareRoot = Math.Sqrt(x) });          //投影
            foreach (var element in collection)
            {
                Console.WriteLine($"sqrt({element.Original}) = {element.SquareRoot}");
            }
        }
        // 这一次的Collection的类型是IEnumerable<Something>,其中Something是由编译器创建的匿名类型。

        // 根据两个属性对序列进行排序
        public static void Call6()
        {
            var collection = Enumerable.Range(-5, 11)
                                        .Select(x => new { Original = x, Square = x * x })
                                        .OrderBy(x => x.Square)                             // 排序
                                        .ThenBy(x => x.Original);
            foreach (var element in collection)
            {
                Console.WriteLine(element);
            }
        }


        // 10.3.6   涉及链接的实际例子
        // 1. 聚合：工资汇总
        // 第一个例子涉及由几个部门组成的一家公司。每个部门都有大量员工，每个员工都有一份工资。假定要对各部门的总工资制作报表，工资最高的部门排在前面。查询很简单：
        //company.Departments
        //.Select(dept => new
        //{
        //    dept.Name,
        //    Cost = dept.Employees.Sum(person => person.Salary)
        //})
        //.OrderByDescending(deptWithCost => deptWithCost.Cost);

        //这个查询用一个匿名类型来记录部门名称（用一个投影初始化器）以及该部门的所有员工的总工资。工资汇总使用的是一个含义明确的Sum扩展方法，它同样来自Enumerable。


        //2. 分组：统计分配给开发者的bug 数量
        //bugs.GroupBy(bug => bug.AssignedTo)
        //.Select(list => new
        //{
        //    Developer = list.Key, Count = list.Count()
        //    })
        //.OrderByDescending(x => x.Count);

        //这个查询使用了GroupBy扩展方法，它按一个投影（本例是分配来修正这个bug的开发者）对原始集合进行分组，结果是一个 IGrouping<TKey,TElement>。GroupBy有多个重载版本，这里使用的是最简单的。
        //然后选择键（开发者的姓名）和分配给他们的bug的数量。之后，我们对结果进行排序，最先显示分配到bug数量最多的开发者。
    }
}
